package fxLib
{
	import fl.transitions.Tween;
	import fl.transitions.TweenEvent;
	import fl.transitions.easing.*;
	
	import flash.display.MovieClip;
	
	public class FXPulseAlpha extends FXFade
	{
		private static const nPULSE_FREQUENCY:Number          = 1500 / 1000;
		private static const nPULSE_ALPHA_MAX:Number          = 1;
		private static const nPULSE_ALPHA_MIN:Number          = 0;
		
		// set defaults for gettersetters
		public var mnAlphaMax:Number                          = nPULSE_ALPHA_MAX;
		public var mnAlphaMin:Number                          = nPULSE_ALPHA_MIN;
		public var mnPulseFrequency:Number                    = nPULSE_FREQUENCY;
		
		public var mcPulseObject:MovieClip;
		
		private var mcAlphaTween:Tween;
		
		private var mbAlphaPulseDone:Boolean;
		
		private var mcPhase:int                               = 0;
		
		private var bStopOnDown:Boolean                       = false;
		private var bStopOnUp:Boolean                         = false;
		
		private var mcWaveformUp:Function                     = None.easeNone; // TRIANGLE default
		private var mcWaveformDown:Function                   = None.easeNone; // TRIANGLE default
		
		private var mcWaveformType:String                     = FXWaveforms.TRIANGLE;
		
		// constructor
		public function FXPulseAlpha( acMCtoPulse:MovieClip, acParams:Object = null )
		{
			// accept parameters if given, in Object format
			if (acParams != null)
			{
				if ( !isNaN( acParams.minAlpha ) )
					mnAlphaMin          = acParams.minAlpha;
				
				if ( !isNaN( acParams.maxAlpha ) )
					mnAlphaMax          = acParams.maxAlpha;
				
				if ( !isNaN( acParams.startAlpha ) )
					mnAlphaMin          = acParams.startAlpha;
				
				if ( !isNaN( acParams.endAlpha ) )
					mnAlphaMax          = acParams.endAlpha;
				
				if ( !isNaN( acParams.fromAlpha ) )
					mnAlphaMin          = acParams.fromAlpha;
				
				if ( !isNaN( acParams.toAlpha ) )
					mnAlphaMax          = acParams.toAlpha;
				
				if ( !isNaN( acParams.pulseFrequency ) )
					mnPulseFrequency    = acParams.pulseFrequency;
				
				if ( !isNaN( acParams.fadeDuration ) )
					mnPulseFrequency    = acParams.fadeDuration;
				
				if ( !isNaN( acParams.duration ) )
					mnPulseFrequency    = acParams.duration;
				
				if ( acParams.hasOwnProperty( "waveform" ) )
				{
					if ( acParams.waveform is String )
					{
						switch (acParams.waveform)
						{
							case FXWaveforms.TRIANGLE:
								mcWaveformUp   = None.easeNone;
								mcWaveformDown = None.easeNone;
								mcWaveformType = FXWaveforms.TRIANGLE;
								break;
							
							case FXWaveforms.SINE:
								mcWaveformUp   = Regular.easeInOut;
								mcWaveformDown = Regular.easeInOut;
								mcWaveformType = FXWaveforms.SINE;
								break;
							
							case FXWaveforms.SQUARE:
								mcWaveformUp   = None.easeNone;
								mcWaveformDown = None.easeNone;
								mcWaveformType = FXWaveforms.SQUARE;
								break;
							
							case FXWaveforms.STRONGSINE:
								mcWaveformUp   = Strong.easeInOut;
								mcWaveformDown = Strong.easeInOut;
								mcWaveformType = FXWaveforms.STRONGSINE;
								break;
							
							case FXWaveforms.SAWTOOTH_UP:
								mcWaveformUp   = None.easeNone;
								mcWaveformDown = None.easeNone;
								mcWaveformType = FXWaveforms.SAWTOOTH_UP;
								mnPulseFrequency *= 2;
								break;
							
							case FXWaveforms.SAWTOOTH_DOWN:
								mcWaveformUp   = None.easeNone;
								mcWaveformDown = None.easeNone;
								mcWaveformType = FXWaveforms.SAWTOOTH_DOWN;
								mnPulseFrequency *= 2;
								break;
							
							case FXWaveforms.SAWTOOTH:
								mcWaveformUp   = None.easeNone;
								mcWaveformDown = None.easeNone;
								mcWaveformType = FXWaveforms.SAWTOOTH_DOWN;
								mnPulseFrequency *= 2;
								break;
								
							default:
								//trace("[FXPulseAlpha] ERROR! Unexpected waveform type '"+acParams.waveform+"'");
								break;
						}
					}
					else
					{
						//trace("[FXPulseAlpha] ERROR! Expected #String type argument for .waveform");
					}
				}
			}
			
			mcPulseObject               = acMCtoPulse;
			
			startAlphaPulse();
		}
		
		// destroy any references
		private function destroy():void
		{
			mcAlphaTween                = null;
			
			mcWaveformUp                = null;
			mcWaveformDown              = null;
			
			mcPulseObject               = null;
			
			mcPhase                     = 3;
			
			//trace("[FXPulseAlpha destroy]");
		}
		
		// allow programmer to stop playback of effect if required!
		public function stop():void
		{
			switch (mcPhase)
			{
				case 1: // fade up
					mcAlphaTween.removeEventListener( TweenEvent.MOTION_FINISH, alphaUpFinished );
					mcAlphaTween.stop();
					
					updateAlpha = 0;
					break;
				
				case 2: // ramp down
					mcAlphaTween.removeEventListener( TweenEvent.MOTION_FINISH, alphaDownFinished );
					mcAlphaTween.stop();
					
					updateAlpha = 0;
					break;
				
				case 3: // after destroy
					// ignore
					break;
				
				default:
					//trace("[FXPulseAlpha stop] Unexpected this is.");
			}
			
			destroy();
		}
		
		// allow programmer to stop pulsing AT THE END OF THE NEXT DOWN CYCLE
		public function stopOnDown():void
		{
			bStopOnDown = true;
			bStopOnUp   = false;
		}
		
		// allow programmer to stop pulsing AT THE END OF THE NEXT DOWN CYCLE
		public function stopOnUp():void
		{
			bStopOnUp   = true;
			bStopOnDown = false;
		}
		
		private function startAlphaPulse():void
		{
			mcPhase = 1; // ramp up
			
			var nStart:Number = mnAlphaMin;
			var nEnd:Number   = mnAlphaMax;
			
			switch (mcWaveformType)
			{
				case FXWaveforms.TRIANGLE:
				case FXWaveforms.SINE:
				case FXWaveforms.STRONGSINE:
				case FXWaveforms.SAWTOOTH_UP:
					nStart = mnAlphaMin;
					nEnd   = mnAlphaMax;
					break;
				
				case FXWaveforms.SQUARE:
					nStart = mnAlphaMax;
					nEnd   = mnAlphaMax;
					break;
				
				case FXWaveforms.SAWTOOTH_DOWN:
					nStart = mnAlphaMax;
					nEnd   = mnAlphaMin;
				    break;
				
				default:
					// not expected
			}
			
			mcAlphaTween = new Tween( this, "updateAlpha", mcWaveformUp, nStart, nEnd, 0.5 * mnPulseFrequency, true );
			mcAlphaTween.addEventListener( TweenEvent.MOTION_FINISH, alphaUpFinished );
		}
		
		private function alphaUpFinished( e:TweenEvent ):void 
		{
			updateAlpha = mnAlphaMax;
			
			mcPhase = 2; // ramp down
			
			var nStart:Number = mnAlphaMax;
			var nEnd:Number   = mnAlphaMin;
			
			switch (mcWaveformType)
			{
				case FXWaveforms.TRIANGLE:
				case FXWaveforms.SINE:
				case FXWaveforms.STRONGSINE:
				case FXWaveforms.SAWTOOTH_DOWN:
					nStart = mnAlphaMax;
					nEnd   = mnAlphaMin;
					break;
				
				case FXWaveforms.SQUARE:
					nStart = mnAlphaMin;
					nEnd   = mnAlphaMin;
					break;
				
				case FXWaveforms.SAWTOOTH_UP:
					nStart = mnAlphaMin;
					nEnd   = mnAlphaMax;
					break;
				
				default:
					// not expected
			}

			mcAlphaTween.removeEventListener( TweenEvent.MOTION_FINISH, alphaUpFinished );
			
			if (mcWaveformType == FXWaveforms.SAWTOOTH_DOWN && bStopOnDown)
			{
				updateAlpha = mnAlphaMin;
				destroy();
				return;
			}
			
			if (!bStopOnUp)
			{
				mcAlphaTween = new Tween( this, "updateAlpha", mcWaveformUp, nStart, nEnd, 0.5 * mnPulseFrequency, true );
				mcAlphaTween.addEventListener( TweenEvent.MOTION_FINISH, alphaDownFinished );
			}
			else
			{
				destroy();
			}
		}
		
		private function alphaDownFinished( e:TweenEvent ):void 
		{
			updateAlpha = mnAlphaMin;
			mbAlphaPulseDone = true;
			
			mcAlphaTween.removeEventListener( TweenEvent.MOTION_FINISH, alphaDownFinished );
			
			if (!bStopOnDown)
			{
				startAlphaPulse();
			}
			else
			{
				destroy();
			}
		}
		
		// set the brightness
		public function set updateAlpha( newValue:Number ):void
		{
			mcPulseObject.alpha = newValue; 		
		}
		
		//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
		
		// getters and setters for all properties
		
		public function set minAlpha( anAlphaMin:Number ):void
		{
			mnAlphaMin = anAlphaMin;
		}
		
		public function get minAlpha():Number
		{
			return mnAlphaMin;
		}
		
		public function set maxAlpha( anAlphamax:Number ):void
		{
			mnAlphaMax = anAlphamax;
		}
		
		public function get maxAlpha():Number
		{
			return mnAlphaMax;
		}
		
		public function set pulseFrequency( anPulseFrequency:Number ):void
		{
			mnPulseFrequency = anPulseFrequency;
		}
		
		public function get pulseFrequency():Number
		{
			return mnPulseFrequency;
		}
		
		public function set startAlpha( anAlphaMin:Number ):void
		{
			mnAlphaMin = anAlphaMin;
		}
		
		public function get startAlpha():Number
		{
			return mnAlphaMin;
		}
		
		public function set endAlpha( anAlphamax:Number ):void
		{
			mnAlphaMax = anAlphamax;
		}
		
		public function get endAlpha():Number
		{
			return mnAlphaMax;
		}
		
		public function set fromAlpha( anAlphaMin:Number ):void
		{
			mnAlphaMin = anAlphaMin;
		}
		
		public function get fromAlpha():Number
		{
			return mnAlphaMin;
		}
		
		public function set toAlpha( anAlphamax:Number ):void
		{
			mnAlphaMax = anAlphamax;
		}
		
		public function get toAlpha():Number
		{
			return mnAlphaMax;
		}
		
		public function set duration( anDuration:Number ):void
		{
			mnPulseFrequency = anDuration;
		}
		
		public function get duration():Number
		{
			return mnPulseFrequency;
		}
		
		public function set fadeDuration( anDuration:Number ):void
		{
			mnPulseFrequency = anDuration;
		}
		
		public function get fadeDuration():Number
		{
			return mnPulseFrequency;
		}
		
		//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
		
	}
}